package com.xiguaji.tiktok.task.blogger.event;

import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.gugee.tiktok.common.model.dto.SlimBloggerDto;
import com.gugee.tiktok.common.model.spider.blogger.BloggerFollowerResponse;
import com.xiguaji.boot.eventbus.Event;
import com.xiguaji.boot.eventbus.EventBusTemplate;
import com.xiguaji.boot.eventbus.IEventListener;
import com.xiguaji.boot.toolkit.ThreadPoolUtils;
import com.xiguaji.tiktok.task.blogger.spider.BloggerSpiderClient;
import java.util.concurrent.ForkJoinPool;

import com.xiguaji.tiktok.task.core.ScheduleTemplate;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class SaveBloggerFollowerEventListener implements IEventListener<SaveBloggerFollowerEventListener.SaveBloggerFollowerEvent> {
    ForkJoinPool forkJoinPool= ThreadPoolUtils.forkJoinPool(20,"SaveBloggerFollower-worker");

    @Autowired
    BloggerSpiderClient bloggerSpiderClient;

    @Autowired
    @Lazy
    EventBusTemplate eventBusTemplate;

    @Autowired
    SlimBloggerDto.SlimBloggerDtoMapper slimBloggerDtoMapper;

    @Autowired
    ScheduleTemplate scheduleTemplate;

    @PostConstruct
    public void init() {
        scheduleTemplate.attach("SaveBloggerFollower-worker", forkJoinPool);
    }

    @SneakyThrows
    @Override
    @Subscribe
    @AllowConcurrentEvents
    public void handle(SaveBloggerFollowerEventListener.SaveBloggerFollowerEvent event) {
        if (CollectionUtils.isEmpty(event.uids)) return;

        forkJoinPool.submit(()->
            event.uids.parallelStream().forEach(uid -> {
                try {
                    run(event, uid);
                } catch (Exception ex) {
                    log.error("SaveBloggerFollower error. uid:" + uid);
                }
            })
        ).get();
    }

    private void run(SaveBloggerFollowerEventListener.SaveBloggerFollowerEvent event, long uid) {
        long min_time = 0;
        boolean isHasMore = true;
        int count = 0;
        try {
            while (isHasMore) {
                BloggerFollowerResponse response = bloggerSpiderClient.getFollowers(uid, min_time, 40);

                if (response == null || CollectionUtils.isEmpty(response.getFollowers())) {
                    log.warn(event.getSource() + " uid:" + uid + " min_time:" + min_time + " count:" + count);
                    break;
                }

                min_time = response.getMin_time();
                isHasMore = response.isHas_more();

                var followers = response.getFollowers();

                List<SlimBloggerDto> users = slimBloggerDtoMapper.mapperUser(followers.stream().collect(Collectors.toList()));

                var saveBloggerEvent = new SaveBloggerEventListener.SaveBloggerEvent(event, users, false);
                eventBusTemplate.post(saveBloggerEvent);
                count += users.size();
            }
            //log.info(event.getSource() + " uid:" + uid + " count:" + count);
        } catch (Exception ex) {
            //记录异常，继续进行接下去的操作
            log.error(event.getSource() + " uid:" + uid + " count:" + count, ex);
        }
    }

    public static class SaveBloggerFollowerEvent extends Event {
        public SaveBloggerFollowerEvent(List<Long> uids) {
            this(null, uids);
        }

        public SaveBloggerFollowerEvent(Event event, List<Long> uids) {
            super(event, "SaveBloggerFollower");
            this.uids = uids;
        }

        private List<Long> uids;
    }
}
